﻿using System;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Resources;
using System.Text;
using System.Windows.Forms;
using System.Xml.Linq;

using Microsoft.WowAddonStudio.Project.Import;
using Microsoft.WowAddonStudio.Project.Import.Ace;

namespace Microsoft.WowAddonStudio.Project.Import.Ace
{
    /// <summary>
    /// Implements interface via which users can specify import and target locations
    /// for ACE import.
    /// </summary>
    public partial class PackageSelectorPane : InnerPane
    {
        #region Lifecycle methods

        /// <summary>
        /// Creates instances of <see cref="PackageSelectorPane"/>.
        /// </summary>
        public PackageSelectorPane()
        {
            InitializeComponent();

            //Set resources
            var res = new ResourceManager(typeof (ImportWizardResources));
            HeaderText = res.GetString("AceImportHeader");
        }

        #endregion

        private class AddonData
        {
            /// <summary>
            /// Gets or sets the title.
            /// </summary>
            /// <value>The title.</value>
            public string Title { get; set; }

            /// <summary>
            /// Gets or sets the description.
            /// </summary>
            /// <value>The description.</value>
            public string Description { get; set; }

            /// <summary>
            /// Gets or sets the URL.
            /// </summary>
            /// <value>The URL.</value>
            public string Url { get; set; }

            /// <summary>
            /// Gets or sets the category.
            /// </summary>
            /// <value>The category.</value>
            public string Category { get; set; }

            /// <summary>
            /// Gets or sets the version.
            /// </summary>
            /// <value>The version.</value>
            public string Version { get; set; }
        }

        private AddonData[] addons;

        /// <summary>
        /// Updates the buttons.
        /// </summary>
        private void UpdateButtons()
        {
            bool hasSelection = lvAddons.SelectedIndices.Count == 1;

            SetWizardButtons(hasSelection ? (WizardButtons.Back | WizardButtons.Next) : WizardButtons.Back);
        }

        private void bwRssLoader_DoWork(object sender, DoWorkEventArgs e)
        {
            // get the addon list rss from wowace
            var wr = (HttpWebRequest) WebRequest.Create("http://files.wowace.com/latest.xml");

            wr.AllowAutoRedirect = true;
            wr.AutomaticDecompression = DecompressionMethods.Deflate | DecompressionMethods.GZip;
            wr.MaximumAutomaticRedirections = 3;
            wr.KeepAlive = false;

            // get the response
            WebResponse resp = wr.GetResponse();

            XDocument doc;

            // make an XDocument from the xml
            using (Stream stream = resp.GetResponseStream())
            using (TextReader tr = new StreamReader(stream, Encoding.UTF8, true))
            {
                doc = XDocument.Load(tr);
            }

            // get all the addons from the xml
            var items = from entry in doc.Element("rss").Element("channel").Elements("item")
                        orderby (string) entry.Element("title")
                        select new AddonData
                               {
                                   Title = (string) entry.Element("title"),
                                   Description = (string) entry.Element("description"),
                                   Category = (string) entry.Element("category"),
                                   Version = (string) entry.Element(XName.Get("version", "http://www.wowace.com/xmlns/wowaddon/")),
                                   Url =
                                       entry.Element("enclosure") == null
                                           ? null
                                           : (string) entry.Element("enclosure").Attribute("url")
                               };

            // cache it
            addons = items.ToArray();

            // remove the "Loading" item from the LV and make it virtual
            Action<ListView> lvUpdate = delegate(ListView lv)
                                        {
                                            lv.Items.Clear();

                                            lv.VirtualMode = true;
                                            lv.VirtualListSize = addons.Length;

                                            // enable the back button
                                            SetWizardButtons(WizardButtons.Back);

                                            lv.SelectedIndexChanged += lvAddons_SelectedIndexChanged;
                                        };

            // run the above update on the UI thread
            lvAddons.BeginInvoke(lvUpdate, lvAddons);
        }

        /// <summary>
        /// Handles the SelectedIndexChanged event of the lvAddons control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.EventArgs"/> instance containing the event data.</param>
        private void lvAddons_SelectedIndexChanged(object sender, EventArgs e)
        {
            UpdateButtons();
        }

        /// <summary>
        /// Handles the SetActive event of the PackageSelectorPane control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.ComponentModel.CancelEventArgs"/> instance containing the event data.</param>
        private void PackageSelectorPane_SetActive(object sender, CancelEventArgs e)
        {
            SetWizardButtons(WizardButtons.None);

            lvAddons.VirtualMode = false;

            lvAddons.Items.Clear();
            lvAddons.Items.Add(new ListViewItem("Loading..."));
            addons = null;

            bwRssLoader.RunWorkerAsync();
        }

        private static readonly string[] lvItemDefaults = {String.Empty, String.Empty, String.Empty};

        /// <summary>
        /// Handles the RetrieveVirtualItem event of the lvAddons control.
        /// </summary>
        /// <param name="sender">The source of the event.</param>
        /// <param name="e">The <see cref="System.Windows.Forms.RetrieveVirtualItemEventArgs"/> instance containing the event data.</param>
        private void lvAddons_RetrieveVirtualItem(object sender, RetrieveVirtualItemEventArgs e)
        {
            int index = e.ItemIndex;

            if (index < 0 || index >= addons.Length)
            {
                e.Item = null;
                return;
            }

            ListViewItem it = e.Item;

            if (it == null)
            {
                it = new ListViewItem(lvItemDefaults);

                e.Item = it;
            }

            AddonData addon = addons[index];

            it.Text = addon.Title;
            it.SubItems[1].Text = addon.Description;
            it.SubItems[2].Text = addon.Version;
        }

        /// <summary>
        /// Gets or sets the settings.
        /// </summary>
        /// <value>The settings.</value>
        public override object Settings
        {
            get
            {
                return lvAddons.SelectedIndices.Count == 0
                           ? null
                           : new AceImportSettings(new Uri(addons[lvAddons.SelectedIndices[0]].Url));
            }
            protected set { }
        }
    }
}